Skip to content

First DeepSeek-OCR working implementation#7

Merged
sfallah merged 5 commits into
sfallah:sf/deepseek-ocrfrom
bluebread:sf/deepseek-ocr
Dec 2, 2025
Merged

First DeepSeek-OCR working implementation#7
sfallah merged 5 commits into
sfallah:sf/deepseek-ocrfrom
bluebread:sf/deepseek-ocr

Conversation

@bluebread

@bluebread bluebread commented Nov 29, 2025

Copy link
Copy Markdown

@sfallah Working towards finishing debugging the vision model and a first functionable implementation for DeepSeek-OCR this weekend. We've made a lot of progress!!

Edit: I finished debugging, and everything magically works! Going to debug other modes next. FYI: The interpolation algorithm used in llama.cpp doesn't quite align with PyTorch's version and can produce slightly different results. It can be confusing when you cares about the correctness.

Changes

  • Replaced manual multi-head attention with ggml_flash_attn_ext in the SAM encoder
  • Replaced manual linear interpolation in get_rel_pos with bilinear interpolation hack (by reshaping tensor to [*, 1, C])
  • Currently forcing all DeepseekOCR vision tensors to F32 for numerical stability during development
  • Added debugging utilities in clip-impl.h e.g. print_tensor_info, print_tensor_sum, save_tensor_to_file

Bug Fixes

  • Fixed incorrect residual connections in SAM
  • Fixed image preprocessing to use proper background color for padding
  • Fixed blocks output not being passed to downsampling neck
  • Fixed rel_pos_resized not being used in get_rel_pos
  • Fixed bicubic interpolation logic by adding proper permute operations before/after interpolation
  • Added F16 type assertion for flash attention masks to catch type mismatches early (debugging this cost me a day...)
  • Fixed the calculation of the expected number of vision tokens (previously hardcoded)

@bluebread bluebread changed the title Debug DeepEncoder (Vision Projector) Debug DeepEncoder (Vision Projector) and first DeepSeek-OCR implementation Nov 29, 2025
@bluebread bluebread changed the title Debug DeepEncoder (Vision Projector) and first DeepSeek-OCR implementation First DeepSeek-OCR working implementation Nov 29, 2025
@bluebread
bluebread marked this pull request as ready for review November 29, 2025 16:47
@bluebread

bluebread commented Nov 30, 2025

Copy link
Copy Markdown
Author

@sfallah Could you please update this branch with the main repository? They've added bicubic interpolation support for cuda/vulkan backends in ggml-org#17022, which we need for SAM.

@sfallah

sfallah commented Nov 30, 2025

Copy link
Copy Markdown
Owner

@bluebread
I have merged master into my branch!
I will review your PR.

@bluebread

Copy link
Copy Markdown
Author

@sfallah I've added an argument --dsocr-mode to llama-mtmd-cli (though I'm not sure if this will be accepted by the maintainers) and debugged the native resolution modes. I'm gonna debug the gundam modes tomorrow, so I'm temporarily converting this PR to draft and will reopen it once all modes pass tests. Here is my testing command:

 ./build/bin/llama-mtmd-cli -m /root/DeepSeek-OCR/DeepSeek-OCR-64x550M-F16.gguf --mmproj /root/DeepSeek-OCR/mmproj-DeepSeek-OCR-F16.gguf --image /root/tensor_files/treewisdom-1024.png -p "Free OCR" --chat-template deepseek -sm none -c 8192 --temp 0.0  --dsocr-mode tiny

FYI: DeepSeek-OCR (the original model in PyTorch, not ours) doesn't seem to work with the testing picture in tools/mtmd. I guess it's because DeepSeek-OCR wasn't trained on images like that, probably? Perhaps you could take a look when you have some free time. BTW, should we add DeepSeek-OCR support to llama-server as well?

@bluebread
bluebread marked this pull request as draft November 30, 2025 17:26
@sfallah

sfallah commented Dec 1, 2025

Copy link
Copy Markdown
Owner

@bluebread
great job!
I am just testing your branch.
With regard to --dsocr-mode I think it will be simpler and more user-friendly to just use image-sizes like 640,1024,1280 instead of modes.

@bluebread

Copy link
Copy Markdown
Author

@sfallah Thanks! I'm not sure if the model was trained for arbitrary image size or not. Another issue is that it would be less intuitive for users to switch from native resolutions to gundam modes or auto mode selection. I'll probably leave this design decision to the maintainers. BTW today I found that img_tool likely adopts a different bicubic interpolation algorithm from GGML/PyTorch ones. This should explain the numerical instability and why it doesn't work well as the original model, e.g. it cannot recognize the title and authors on the cover of DeepSeek-OCR paper (although it can extract the abstract). I'll work on fixing this later.

@sfallah

sfallah commented Dec 1, 2025

Copy link
Copy Markdown
Owner

@bluebread

  • ok, we can maybe add the image-sizes in the description of --dsocr-mode so the user knows what sizes the different modes can result in.

  • I was actually wondering why stb_image_resize2.h was not used for image pre-processing in mtmd, like stb_image.h is used for loading the image-bitmap.
    It is maybe worth trying to resize with stb_image_resize2.h.

@sfallah

sfallah commented Dec 1, 2025

Copy link
Copy Markdown
Owner

@bluebread

e.g. it cannot recognize the title and authors on the cover of DeepSeek-OCR paper (although it can extract the abstract). I'll work on fixing this later.

Screenshot 2025-12-01 at 13 33 01 I don't see any problem with title and authors here?
lbuild/bin/llama-mtmd-cli \
-m gguf_models/deepseek-ai/ds-ocr-lm.gguf \
--mmproj gguf_models/deepseek-ai/mmproj-deepdeek-ocr.gguf \
--image tmp/mtmd_test_data/Deepseek-OCR-2510.18234v1_page1.png \
-p "<|grounding|>Convert the document to markdown." \
--chat-template deepseek \
--dsocr-mode base
base```

@bluebread

Copy link
Copy Markdown
Author

I don't see any problem with title and authors here?

@sfallah You can try replacing the prompt with "Free OCR" and testing other images. It randomly appears/disappears. A little bit puzzling. Hopefully we can wrap up this feature within a few days and then shift our attention to llama-server, which might be more necessary for most users.

@sfallah

sfallah commented Dec 2, 2025

Copy link
Copy Markdown
Owner

@bluebread
Is this PR actually ready?
I ask because it is still draft?

@bluebread
bluebread marked this pull request as ready for review December 2, 2025 07:35
@bluebread

Copy link
Copy Markdown
Author

@sfallah Yes, this PR is ready now. We can let the maintainers review it first. I was thinking about how to replace the interpolation with the correct approach, but others might have better solutions, so we don't need to figure it all out before the reivew.

@sfallah
sfallah merged commit 6b0e7cd into sfallah:sf/deepseek-ocr Dec 2, 2025
@sfallah

sfallah commented Dec 2, 2025

Copy link
Copy Markdown
Owner

@bluebread

  1. I will finalise the PR tomorrow.
  2. I have merged with master.
  3. I have also uploaded f32 versions of the GGUF models on HF hub (see PR). Other quant version will follow after testing.

We need to take care of the CI jobs and make sure that all CI actions are successful.
I suggest that we take care of llama-server in a new PR.

@sfallah

sfallah commented Dec 2, 2025

Copy link
Copy Markdown
Owner

@bluebread
I have given you direct access to the repo.

@bluebread

Copy link
Copy Markdown
Author

@sfallah Thanks! I agree that we should open another PR for llama-server.

@sfallah

sfallah commented Dec 4, 2025

Copy link
Copy Markdown
Owner

@bluebread
I can take care of the clean up if you want?

@bluebread

Copy link
Copy Markdown
Author

@sfallah Thank you! I've done some cleanup and fixed tensor naming for image newline and view separator. Could you help with: replace with some constants with configurable hyperparameters from metadata and add some comments to explain the DeepSeek-OCR algorithm for better readability. I'm going to fix the LM part.

sfallah pushed a commit that referenced this pull request Apr 28, 2026
)

* ggml: backend-agnostic tensor parallelism

* support for GPT-OSS, Qwen 3 MoE

* partial Vulkan fix

* add support for 4/8 GPUs

* unconditional peer access

* re-use buffers + ggml contexts

* fix output pattern

* NCCL support

* GGML: HIP: add RCCL support

* Remove shfl and AllReduce from backend interface

* move allocation workaround out of ggml-alloc.c

* 2d tensor set/get support

* Fix the seg fault without NCCL

* Apply suggestion from JohannesGaessler

* support for tensor dims % n_devs != 0

* fix view_offs scaling

* arbitrary num. of GPUs/tensor split

* fix compilation

* better granularity estimate

* Support device-specific host buffer types if all underlying backends expose the same type. This allows using pinned memory instead of pageable memory for CUDA.

Fix compilation errors.

* partial Qwen 3 Next support

* Fix qwen3 30b (#8)

* Fix crash with Qwen-30B-A3B Q4_0

Qwen-30B-A3B Q4_0 has an intermediate dimension of 768. Using a granularity of 256 forces an uneven split between GPUs, which is not supported by the current implementation.

* Decide block size based on tensor quantization type

* Fix crashes due to KV cache serialization (#9)

KV cache serialization requires non-zero offsets on the tensor. Add support in the meta backend to set/get a tensor with a non-zero offset.

* metal : fix build (#7)

* static memory allocations, fix usage count

* fix tensor granularity

* more even memory distribution

* use BF16 for allreduce

* rebase fixup

* better error message for unsupported architectures

* Fix device mismatch during scatter of allReduce. (#11)

There is a mismatch between the dst buffer device and the backend device, causing the use of sync copies

* Enable the previous allreduce implementation. It is better in both perf and stability (ggml-org#12)

* delay AllReduce for Moe for less I/O

* build : clean-up compile warnings

* backend : move most of the meta backend API to ggml-backend-impl.h

* cont : hide unused public API in the implementation

* llama : use llama_device + remove ggml_backend_dev_is_meta()

* ggml-backend : remove unused alloc include

* minor : remove regex include

* ggml : introduce ggml-ext.h for staging new APIs

* rebase fixup

* fix tests

* llama : more robust logic for determining Meta devices (ggml-org#16)

* llama : more robust logic for determining Meta devices

* cont : fix devs size check

Co-authored-by: Johannes Gäßler <johannesg@5d6.de>

* cont : fix log type

Co-authored-by: Johannes Gäßler <johannesg@5d6.de>

---------

Co-authored-by: Johannes Gäßler <johannesg@5d6.de>

* disable roundtrip for meta backend

* fix arch selection

* Qwen 3.5 support

* fix Gemma 4 MoE

* fix OpenVino, SYCL

* fix test-llama-archs for CPU-only builds

* Fix Qwen 3.5 MoE

* disable meta backend tests for WebGPU

* tests : filter CPU-based devices from the Meta backend tests (ggml-org#17)

* meta : formatting, naming, indentation (ggml-org#18)

* formatting : llama-model.cpp

* formatting : ggml-ext.h

* formatting : ggml-backend-meta.cpp

* meta : add TODO

* add documentation

* better error messages

* fix GPT-OSS

---------

Co-authored-by: Carl Philipp Klemm <carl@uvos.xyz>
Co-authored-by: Gaurav Garg <gaugarg@nvidia.com>
Co-authored-by: Georgi Gerganov <ggerganov@gmail.com>
sfallah pushed a commit that referenced this pull request May 19, 2026
* spec: support MTP

* fix batch size

* rename files

* cont : simplify (#7)

* MTP: clean-up (#9)

* MTP: clean-up

* review: use llama_context_type instead of llama_graph_type

* review: remove llama_model_has_mtp

* review: fix convert issues

* convert: fix pycheck

* review: formatting

* use `mtp-` for identifying mtp models

* convert: fix mtp conversion

* mtp -> draft-mtp

* remove unused llama_arch

* add need_embd in speculative

* llama: allow partial seq_rm for GDN models for speculative decoding

Currently speculative checkpoint needs to restart from a checkpoint
after some draft tokens are not accepted, this leads to some wastage in
running the target again. This PR adds the ability to rollback upto
`draft_max` by storing the GDN intermediates.

* fix pending state

* vulkan: add GDN partial rollback

* meta: extend check to axis 1

* metal: add GDN partial rollback

Extend the gated delta net kernel to store intermediate states for
partial rollback support on the Metal backend.

- Add K (snapshot slot count) as a function constant
- Read input state from slot 0 of the 3D state tensor
- Write intermediate states to different slots during token loop
- For K=1, maintain backward-compatible single-slot behavior

Ref: ggml-org@8c05923

Assisted-by: llama.cpp:local pi

* delta_net_base: use ggml_pad instead of new_tensor

* review: add need_rs_seq

* review: rename part_bounded to n_rs

* review: deslop comments

* review: rename, add asserts

* server : adjust checkpoint logic (#11)

* server : adjust checkpoint logic

* cont : rm asserts

* server-context: fix early exit

* spec : fix compatibility with n-gram and add TODOs (ggml-org#13)

* metal : cleanup

* llama : fix faulty bitwise check in recurrent memory

* server : disable RS-based MTP in combination with other spec types

* spec : add TODOs

* cont : fix comment

* cont : update comment

* common : fix logic for ngram + mtp compat

* llama-memory: enable checkpointing with partial rollback

* cont: add test-case for loading into a dirty ctx

* llama-memory-recurrent: clear rs_idx in clear

* download: fix mtp path

* llama-arch: fix enorm op

* docs: update docs

* conversion: fix type annotations

---------

Co-authored-by: Georgi Gerganov <ggerganov@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants